#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015  Data Enlighten Technology (Beijing) Co.,Ltd


import json
import os
import time
import requests
import Lib.Logger.log4py as logging
from mj_parser import common_errors
from xml.etree import ElementTree as etree
from xml.etree.ElementTree import Element, SubElement, ElementTree
from xml.dom import minidom
requests.packages.urllib3.disable_warnings()

USER_INFO = {
    "user_name": 'eu333333',
    "pass_word": 'bmwetk1'
}

class BmwWebSource:
    DATA_URL = 'https://etk-webservices.bmw.com/restapi/rest/etk_webservices/trf_fahrzeug_id/do_transfer'
    ONLNE_URL = 'https://www.parts.bmwgroup.com/tetis/startTetisAction.do?DOMAIN=Internet'
    LIGIN_URL = 'https://www.parts.bmwgroup.com/tetis/startTetisAction.do'
    TRANS_URL = 'https://www.parts.bmwgroup.com/tetis/starteApplikationAction.do?ENTRY_ID=WebETK_START'
    AUTH_URL = 'https://www.parts.bmwgroup.com/tetis/zeigePortalAnsicht.do'

    DATA_HEADERS = {
        'user_id': USER_INFO['user_name'],
        'Content-Type': 'application/xml',
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
        'Host': 'etk-webservices.bmw.com',
        'Accept': 'text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2',
        'Connection': 'keep-alive'
    }

    LOGIN_HEADERS = {
        'Host': 'www.parts.bmwgroup.com',
        'Connection': 'keep-alive',
        'Content-Length': '42',
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Referer': 'https://www.parts.bmwgroup.com/tetis/startTetisAction.do?DOMAIN=Internet',
        'Accept-Language': 'zh-CN,zh;q=0.9'
    }

    AUTH_HEADERS = {
        'Host': 'www.parts.bmwgroup.com',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Referer': 'https://www.parts.bmwgroup.com/tetis/portal/portaluser/appInWindow.jsp?HM=true&HL=false&WebETK&WebETK_START',
        'Accept-Encoding': 'gzip, deflate, br'
    }

    def __init__(self, root_path='.'):
        self.logger = logging.get_logger('crawler', 'BmwWebSource')
        self.root_path = root_path
        self.conf_path = os.path.join(root_path, 'conf')
        self.cookie_file = os.path.join(self.conf_path, 'bmw_cookie.txt')
        #self.data_path = os.path.join(root_path, "data")
        self.data_path = os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")),'data')
        print(self.data_path)
        self.session = requests.Session()


    def get_data(self, str_vin, brand, group):

        vin_file = self.search_vin(str_vin)

        if vin_file is None:
            return common_errors.ERR_TCP_ERROR, None
        return common_errors.ERR_SUCCESS, str_vin

    def login(self):
        res_online = self.session.get(BmwWebSource.ONLNE_URL, verify=False, timeout=30)
        js_session_id = res_online.cookies.get('JSESSIONID')
        session_id = js_session_id[:js_session_id.find('.')]

        login_headers = dict(BmwWebSource.LOGIN_HEADERS)
        login_headers['Cookie'] = 'JSESSIONID='+js_session_id
        payload_str = 'LOGON_USERID={0}&LOGON_PASSWD={1}'
        payload = payload_str.format(USER_INFO['user_name'],USER_INFO['pass_word'])
        res_login, code_login = self.request_post(BmwWebSource.LIGIN_URL,payload,headers=login_headers, decode_json=False)

        trans_url = BmwWebSource.TRANS_URL
        trans_headers = {'Cookie':'JSESSIONID='+js_session_id+'; ASAP_FAILOVER_DOMAIN_KEY=Internet; ASAP_FAILOVER_SESSION_ID='+session_id}
        res_trans = self.session.get(trans_url,headers=dict(trans_headers), verify=False, timeout=30)

        auth_headers = dict(BmwWebSource.AUTH_HEADERS)
        auth_coolie_str ='JSESSIONID={0}; ASAP_FAILOVER_DOMAIN_KEY=Internet; ASAP_FAILOVER_SESSION_ID={1}'
        cookie_value = auth_coolie_str.format(js_session_id, session_id)
        auth_headers['Cookie'] = cookie_value
        res_auth = self.session.get(BmwWebSource.AUTH_URL, headers=dict(auth_headers), verify=False, timeout=30)

        #print(res_auth)
        #print(res_auth.content)
        return session_id

    def search_vin(self, vin):
        cookie_file = self.cookie_file
        session_id = ''

        if not (os.path.exists(cookie_file) and os.path.isfile(cookie_file)):
            with open(cookie_file, 'w') as f_cre:
                f_cre.write('')
        with open(cookie_file, 'r') as f:
            session_id = f.read()

        xml_str = self.get_xml_request_body(vin, session_id)
        headers = dict(BmwWebSource.DATA_HEADERS)
        headers['PSESSID'] = session_id
        content, code = self.request_post(BmwWebSource.DATA_URL, xml_str, headers, decode_json=False)

        if code == 200:
            pass
            # print(content)
        elif code == 401:
            # login again
            session_id_new = self.login()

            with open(cookie_file, 'w') as fo:
                fo.write(session_id_new)

            xml_str = self.get_xml_request_body(vin, session_id_new)
            headers = dict(BmwWebSource.DATA_HEADERS)
            headers['PSESSID'] = session_id_new
            content, code = self.request_post(BmwWebSource.DATA_URL, xml_str, headers, decode_json=False)
            #print(code)
            #print(content)

        vin_file = os.path.join(self.data_path, vin+'.txt')
        with open(vin_file, 'w', encoding='utf8') as vin_f:
            vin_f.write(content)

        return content

    def request_get(self, url, decode_json=True):
        ret = self.session.get(url, headers=BmwWebSource.HEADERS, proxies=BmwWebSource.PROXIES, verify=False, timeout=30)

        if ret.status_code != 200:
            self.logger.error(url)
            self.logger.error(ret.text)
            return None

        if decode_json:
            return ret.json()

        return ret.text

    def request_post(self, url, payload, headers, decode_json=True):

        if type(payload) != str:
            payload = json.dumps(payload)
        ret = self.session.post(url, data=payload, headers=headers, verify=False, timeout=30)
        if ret.status_code != 200:
            # self.logger.error(url)
            # self.logger.error(payload)
            # self.logger.error(ret.text)
            return None, ret.status_code

        if decode_json:
            return ret.json(), ret.status_code

        return ret.text, ret.status_code

    def get_xml_request_body(self, FAHRGESTELLNUMMER, session_id):

        # 生成根节点
        trfFahrzeugId = Element('trfFahrzeugId')
        # 生成第一个子节点 head
        mCommand = SubElement(trfFahrzeugId, 'mCommand')
        # head 节点的子节点
        mCommandId = SubElement(mCommand, 'mCommandId')
        mCommandId.text = '302'
        mName = SubElement(mCommand, 'mName')
        mName.text = 'GET_IGDOM_BEDINGUNGEN'
        mAsapRelevant = SubElement(mCommand, 'mAsapRelevant')
        mAsapRelevant.text = 'false'

        ID = SubElement(trfFahrzeugId, 'ID')
        ID.text = '24'

        serverParameter = SubElement(trfFahrzeugId, 'serverParameter')
        entry = SubElement(serverParameter, 'entry')
        key = SubElement(entry, 'key')
        key.text = 'PSESSID'
        value = SubElement(entry, 'value')
        value.text = session_id
        entry1 = SubElement(serverParameter, 'entry')
        key1 = SubElement(entry1, 'key')
        key1.text = 'user_id'
        value1 = SubElement(entry1, 'value')
        value1.text = USER_INFO['user_name']

        mAsapSessionId = SubElement(trfFahrzeugId, 'mAsapSessionId')
        mAsapSessionId.text = session_id

        mAsapUserId = SubElement(trfFahrzeugId, 'mAsapUserId')
        mAsapUserId.text = USER_INFO['user_name']

        mForceLocalServerOnly = SubElement(trfFahrzeugId, 'mForceLocalServerOnly')
        mForceLocalServerOnly.text = 'false'

        mIgdom = SubElement(trfFahrzeugId, 'mIgdom')
        mIgdom.text = 'false'

        forceAsapLogin = SubElement(trfFahrzeugId, 'forceAsapLogin')
        forceAsapLogin.text = 'false'

        m_HashMap = SubElement(trfFahrzeugId, 'm_HashMap')
        item = SubElement(m_HashMap, 'item')
        item.set('key', 'language')
        STRING_0 = SubElement(item, 'STRING')
        STRING_0.text = 'zh'
        item1 = SubElement(m_HashMap, 'item')
        item1.set('key', 'FAHRGESTELLNUMMER')
        STRING_1 = SubElement(item1, 'STRING')
        STRING_1.text = FAHRGESTELLNUMMER

        #tree = ElementTree(trfFahrzeugId)
        xml_string_temp = etree.tostring(trfFahrzeugId)
        tree = minidom.parseString(xml_string_temp)
        xml_string = tree.toxml()
        return xml_string


if __name__ == '__main__':

    lr = BmwWebSource()

    code, vin_file = lr.get_data('LBVKY110XJSR42940', '', '')
    print('code:' + code)
    print(vin_file)
